package wasnake.engine;

import java.util.ArrayList;
import java.util.Timer;

import wasnake.actors.Actor;
import wasnake.actors.Cell;
import wasnake.grid.AbstractGrid;
import wasnake.grid.Grid;
import wasnake.grid.Location;

public class Board<E> extends AbstractGrid<E>{
	private Grid<Cell> grid;
	private Object[][] occupantArray; // the array storing the grid elements
	
    /**
     * Constructs an empty bounded grid with the given dimensions.
     * (Precondition: <code>rows > 0</code> and <code>cols > 0</code>.)
     * @param rows number of rows in BoundedGrid
     * @param cols number of columns in BoundedGrid
     */
    public Board(int rows, int cols) {
        if (rows <= 0)
            throw new IllegalArgumentException("rows <= 0");
        if (cols <= 0)
            throw new IllegalArgumentException("cols <= 0");
        occupantArray = new Object[rows][cols];
    }
    
    @Override
    public int getNumRows() {
        return occupantArray.length;
    }
    
    @Override
    public int getNumCols() {
        return occupantArray[0].length;
    }
    
    @Override
    public boolean isValid(Location loc) {
        return 0 <= loc.getRow() && loc.getRow() < getNumRows()
                && 0 <= loc.getCol() && loc.getCol() < getNumCols();
    }
    
    @Override
    public ArrayList<Location> getOccupiedLocations() {
        ArrayList<Location> theLocations = new ArrayList<Location>();

        // Look at all grid locations.
        for (int r = 0; r < getNumRows(); r++) {
            for (int c = 0; c < getNumCols(); c++) {
                // If there's an object at this location, put it in the array.
                Location loc = new Location(r, c);
                if (get(loc) != null)
                    theLocations.add(loc);
            }
        }

        return theLocations;
    }

    @Override
    public E get(Location loc) {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        return (E) occupantArray[loc.getRow()][loc.getCol()]; // unavoidable warning
    }
    
    @Override
    public E put(Location loc, E obj) {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        if (obj == null)
            throw new NullPointerException("obj == null");

        // Add the object to the grid.
        E oldOccupant = get(loc);
        occupantArray[loc.getRow()][loc.getCol()] = obj;
        return oldOccupant;
    }
    
    @Override
    public Location put(E obj) {
        if (obj == null)
            throw new NullPointerException("obj == null");

        // Add the object to the grid.
        Location loc;
        for(int row = 0; row < getNumRows(); row++) {
                for(int col = 0; col < getNumCols(); col++) {
                        loc = new Location(row, col);
                        if(get(loc) == null) {
                                occupantArray[loc.getRow()][loc.getCol()] = obj;
                                return loc;
                        }
                }
        }
        return null;
    }

    @Override
    public E remove(Location loc) {
        if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        
        // Remove the object from the grid.
        E r = get(loc);
        occupantArray[loc.getRow()][loc.getCol()] = null;
        return r;
    }
    
    @Override
    public ArrayList<Location> getAllLocations() {
        ArrayList <Location> locs = new ArrayList<Location>();
        for (int row = 0; row < occupantArray.length; row ++)
            for (int col = 0; col < occupantArray [0].length; col ++)
                locs.add (new Location(row, col));
        return locs;
    }
}

